#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <pthread.h>
#include <unistd.h>

#include "garbage.h"
#include "uartTool.h"
#include "pwm.h"
#include "oled_demo.h"
#include "socket.h"

int serial_fd = -1;    // 串口fd
pthread_cond_t cond;   // 条件变量
pthread_mutex_t mutex; // 互斥锁

static int detect_process(const char *process_name)
{
    int n = -1;
    FILE *strm;
    char buf[128] = {0};
    sprintf(buf, "ps -ax |grep %s|grep -v grep", process_name);
    if ((strm = popen(buf, "r")) != NULL)
    {
        if (fgets(buf, sizeof(buf), strm) != NULL)
        {
            n = atoi(buf);
        }
    }
    else
    {
        return -1;
    }

    pclose(strm);
    return n;
}

#if 0
int main(int argc, char *argv[])
{
    int serial_fd = -1;
    int ret = -1;
    int len = 0;
    char *category = NULL;
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA};
    wiringPiSetup();
    garbage_initialize();
    ret = detect_process("mjpg_streamer");
    if(ret == -1)
    {
        goto END;
    }
    serial_fd = myserialOpen(SERIAL_DEV, BAUD); // open serial
    if (-1 == serial_fd)
    {
        goto END;
    }
    while (1)
    {
        /* code */
        buffer[2] = 0x00;
        len = serialGetstring(serial_fd, buffer);
        printf("len = %d, buf[2] = 0x%x\n", len, buffer[2]);
        if (len > 0 && buffer[2] == 0x46)
        {
            /* code */
            system(WGET_CMD); // photo
            category = garbage_category(category);
            if (strstr(category, "干垃圾"))
            {
                buffer[2] = 0x41;
            }
            else if (strstr(category, "湿垃圾"))
            {
                buffer[2] = 0x42;
            }
            else if (strstr(category, "可回收垃圾"))
            {
                buffer[2] = 0x43;
            }
            else if (strstr(category, "有害垃圾"))
            {
                buffer[2] = 0x44;
            }
            else // 未识别到
            {
                buffer[2] = 0x45;
            }
            serialSendstring(serial_fd, buffer, 6);
            if(buffer[2] != 0x45)
            {
                pwm_write(PWM_GARBAGE);
                delay(2000);
                pwm_stop(PWM_GARBAGE);
            }
            buffer[2] = 0x00;
            remove(GARBAGE_FILE);
        }
    }
    close(serial_fd);
END:
    garbage_final();
    return 0;
}
#endif
// 获取语音线程
void *pget_voice(void *arg)
{
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA};
    int len = 0;
    if (-1 == serial_fd)
    {
        printf("%s|%s|%d", __FILE__, __func__, __LINE__);
        pthread_exit(0);
    }
    while (1)
    {
        len = serialGetstring(serial_fd, buffer);
        printf("%s|%s|%d", __FILE__, __func__, __LINE__);
        if (len > 0 && buffer[2] == 0x46)
        {
            printf("%s|%s|%d", __FILE__, __func__, __LINE__);
            pthread_mutex_lock(&mutex);
            buffer[2] = 0x00;
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
        }
    }
    pthread_exit(0);
}

// 播报
void *psend_voice(void *arg)
{
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;
    if (-1 == serial_fd)
    {
        printf("%s|%s|%d", __FILE__, __func__, __LINE__);
        pthread_exit(0);
    }
    if (NULL != buffer)
    {
        serialSendstring(serial_fd, buffer, 6);
    }

    pthread_exit(0);
}
// 开盖
void *popen_trash_can(void *arg)
{
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;

    if (buffer[2] != 0x45)
    {
        pwm_write(PWM_GARBAGE);
        delay(2000);
        pwm_stop(PWM_GARBAGE);
    }
    pthread_exit(0);
}

// oled显示
void *poled_show(void *arg)
{
    pthread_detach(pthread_self());
    myoled_init();
    oled_show(arg);
    pthread_exit(0);
}

void *pcategory(void *arg) // 阿里云垃圾识别
{
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA};
    char *category = NULL;
    pthread_t send_voice_pid, trash_tid, oled_pid;
    while (1)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);
        pthread_mutex_unlock(&mutex);
        buffer[2] = 0x00;
        system(WGET_CMD); // 拍照
        if (0 == access(GARBAGE_FILE, F_OK))
        {
            category = garbage_category(category); //
            if (strstr(category, "干垃圾"))
            {
                buffer[2] = 0x41;
            }
            else if (strstr(category, "湿垃圾"))
            {
                buffer[2] = 0x42;
            }
            else if (strstr(category, "可回收垃圾"))
            {
                buffer[2] = 0x43;
            }
            else if (strstr(category, "有害垃圾"))
            {
                buffer[2] = 0x44;
            }
            else // 未识别到
            {
                buffer[2] = 0x45;
            }
            // 语音播报线程
            pthread_create(&send_voice_pid, NULL, psend_voice, (void *)buffer);
            // 舵机开盖线程
            pthread_create(&trash_tid, NULL, popen_trash_can, (void *)buffer);
            // oled显示线程
            pthread_create(&oled_pid, NULL, poled_show, (void *)buffer);

            remove(GARBAGE_FILE);
        }
    }

    pthread_exit(0);
}

// 网络线程
void *pSocket_contral(void *arg)
{
    int s_fd = -1, c_fd = -1;
    struct sockaddr_in c_addr;
    char buffer[6];
    int nread = -1;
    int c_len = sizeof(struct sockaddr_in);
    s_fd = socket_init(IPADDR, IPPORT);
    printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);
    if (-1 == s_fd)
    {
        pthread_exit(0);
    }
    sleep(3);

    while (1)
    {
        c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &c_len);
        int keepalive = 1; // 开启TCP KeepAlive功能
        int keepidle = 5;  // tcp_keepalive_time 3s内没收到数据开始发送心跳包
        int keepcnt = 3;   // tcp_keepalive_probes 每次发送心跳包的时间间隔,单位秒
        int keepintvl = 3; // tcp_keepalive_intvl 每3s发送一次心跳包
        setsockopt(c_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive,sizeof(keepalive));
        setsockopt(c_fd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(keepidle));
        setsockopt(c_fd, SOL_TCP, TCP_KEEPCNT, (void *)&keepcnt, sizeof(keepcnt));
        setsockopt(c_fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(keepintvl));
        printf("%s|%s|%d: Accept a connection from %s:%d\n", __FILE__, __func__,
               __LINE__, inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port));
        if (c_fd == -1)
        {
            perror("accept");
            continue;
        }
        while(1)
        {
            memset(buffer,0,sizeof(buffer));
            nread = recv(c_fd,buffer,sizeof(buffer),0);
            printf("%s|%s|%d,|nread:%d,buffer:%s\n", __FILE__, __func__,__LINE__,nread,buffer);
            if(nread > 0)
            {
                if(strstr(buffer,"open"))
                {
                    pthread_mutex_lock(&mutex);
                    pthread_cond_signal(&cond);
                    pthread_mutex_unlock(&mutex);
                }
            }
            else if(0 == nread || -1 == nread)
            {   
                break;
            }
        }

    }
    pthread_exit(0); // 退出线程
}

int main(int argc, char *argv[])
{
    garbage_initialize(); // python初始化
    wiringPiSetup();
    pthread_t get_voice_tid, category_tid, mySocket_tid;
    int ret = -1;
    ret = detect_process("mjpg_streamer");
    if (ret == -1)
    {
        goto END;
    }

    serial_fd = myserialOpen(SERIAL_DEV, BAUD);
    if (serial_fd == -1)
    {
        printf("open serial failed \n");
        goto END;
    }
    printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);
    // 开启语音线程
    pthread_create(&get_voice_tid, NULL, pget_voice, NULL);
    // 开启阿里云交互线程
    pthread_create(&category_tid, NULL, pcategory, NULL);
    // 开启socket线程
    pthread_create(&mySocket_tid, NULL, pSocket_contral, NULL);
    // 线程等待
    pthread_join(get_voice_tid, NULL);
    pthread_join(category_tid, NULL);
    pthread_join(mySocket_tid, NULL);

    close(serial_fd);
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

END:
    garbage_final(); // 释放python解释器
    return 0;
}
